#include "Stdafx.h"

#include "Engine.h"

volatile ZOBRIST_KEY ZobristTable[BOARD_SIZE][MAX_FIGURE];
volatile ZOBRIST_KEY keyColor;
volatile bool g_oZobristInit = false;

ZOBRIST_KEY GenerateKey()
{
	return rand()^((ZOBRIST_KEY)rand()<<15)^((ZOBRIST_KEY)rand()<<30)^((ZOBRIST_KEY)rand()<<45)^((ZOBRIST_KEY)rand()<<60);
}

void DumpZobristTable()
{
	FILE* fp;
	fp = _wfopen(L"c:\\Log\\Zobrist.log", L"w");

	for(int i = 0; i < BOARD_SIZE; i++)
	{
		for(int j = 0; j < MAX_FIGURE; j++)
		{
			fprintf(fp, "%016llX\n", ZobristTable[i][j]);
		}
	}

	fprintf(fp, "%016llX\n", keyColor);

	fclose(fp);
}

void CreateZobristTable()
{
	if(g_oZobristInit)
		return;

	time_t now;
    srand((unsigned int)time(&now));

	for(int i = 0; i < BOARD_SIZE; i++)
		for(int j = 0; j < MAX_FIGURE; j++)
			ZobristTable[i][j] = GenerateKey();

	keyColor = GenerateKey();

	g_oZobristInit = true;
	//DumpZobristTable();
}

ZOBRIST_KEY GenerateBoardKey(BitBoard* bb, bool bWhite)
{
	ZOBRIST_KEY key = 0;

	// white man
	uint32 wm = bb->wm;
	while(wm)
	{
		key ^= ZobristTable[LSB(wm)][0];
		wm = wm & (wm - 1);
	}

	// black man
	uint32 bm = bb->bm;
	while(bm)
	{
		key ^= ZobristTable[LSB(bm)][1];
		bm = bm & (bm - 1);
	}

	// white king
	uint32 wk = bb->wk;
	while(wk)
	{
		key ^= ZobristTable[LSB(wk)][2];
		wk = wk & (wk - 1);
	}

	// black king
	uint32 bk = bb->bk;
	while(bk)
	{
		key ^= ZobristTable[LSB(bk)][3];
		bk = bk & (bk - 1);
	}

	if(bWhite == false)
		key ^= keyColor;

	return key;
}

ZOBRIST_KEY GenerateBoardKey64(BitBoard64* bb, bool bWhite)
{
	ZOBRIST_KEY key = 0;

	// white man
	uint64 wm = bb->wm;
	while(wm)
	{
		key ^= ZobristTable[LSB64(wm)][0];
		wm = wm & (wm - 1);
	}

	// black man
	uint64 bm = bb->bm;
	while(bm)
	{
		key ^= ZobristTable[LSB64(bm)][1];
		bm = bm & (bm - 1);
	}

	// white king
	uint64 wk = bb->wk;
	while(wk)
	{
		key ^= ZobristTable[LSB64(wk)][2];
		wk = wk & (wk - 1);
	}

	// black king
	uint64 bk = bb->bk;
	while(bk)
	{
		key ^= ZobristTable[LSB64(bk)][3];
		bk = bk & (bk - 1);
	}

	if(bWhite == false)
		key ^= keyColor;

	return key;
}

 // template overlap for generating zobrist keys
/////////////////////////////////////////////////////////////////////////////////////////

template<typename BB> ZOBRIST_KEY GenerateZobristHash(BB* bb, bool bWhite)
{
	return 0;
}

template<> ZOBRIST_KEY GenerateZobristHash<BitBoard>(BitBoard* bb, bool bWhite)
{
	return GenerateBoardKey(bb, bWhite);
}

template<> ZOBRIST_KEY GenerateZobristHash<BitBoard64>(BitBoard64* bb, bool bWhite)
{
	return GenerateBoardKey64(bb, bWhite);
}
